import {
    createConnection,
    TextDocuments,
    Diagnostic,
    DiagnosticSeverity,
    ProposedFeatures,
    InitializeParams,
    DidChangeConfigurationNotification,
    CompletionItem,
    CompletionItemKind,
    TextDocumentPositionParams,
    TextDocumentSyncKind,
    InitializeResult,
    DocumentFormattingParams,
    TextEdit,
    Range,
    Position
} from 'vscode-languageserver/node';

import { TextDocument } from 'vscode-languageserver-textdocument';
import { WorkspaceFolder } from 'vscode-languageserver/node';

// 创建连接
const connection = createConnection(ProposedFeatures.all);

// 文档管理器
const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);

let hasConfigurationCapability = false;
let hasWorkspaceFolderCapability = false;
let hasDiagnosticRelatedInformationCapability = false;

// 墨言语言关键字
const MOYAN_KEYWORDS = [
    '篇章', '引言', '正文', '结语', '毕',
    '有', '恒有', '者', '为', '曰', '使', '令', '取', '归', '于', '与', '以',
    '物之属', '乃', '之属', '其', '父', '生', '灭',
    '如', '则', '否则', '否则如', '当', '之时', '行', '直至', '自', '至', '步', '循环', '遍', '止', '续',
    '托付', '静候', '众行', '合其果',
    '试', '若有', '抛', '终',
    '取', '示',
    '真', '伪', '无',
    '集', '辞', '汇', '组',
    '加', '减', '乘', '除', '余', '大於', '小於', '等於', '不等於', '大於等於', '小於等於', '且', '或', '非'
];

// 语法检查器
class MoyanSyntaxChecker {
    private diagnostics: Diagnostic[] = [];
    private text: string;
    private lines: string[];

    constructor(text: string) {
        this.text = text;
        this.lines = text.split('\n');
        this.diagnostics = [];
    }

    check(): Diagnostic[] {
        this.checkStructure();
        this.checkKeywords();
        this.checkBrackets();
        this.checkFunctions();
        this.checkVariables();
        return this.diagnostics;
    }

    // 检查基本结构
    private checkStructure(): void {
        const hasChapter = this.text.includes('篇章');
        const hasEnd = this.text.includes('毕');

        if (!hasChapter && this.text.trim().length > 0) {
            this.addDiagnostic(0, 0, '墨言程序应该以"篇章"开始', DiagnosticSeverity.Error);
        }

        // 检查篇章结构完整性
        const chapterMatches = this.text.match(/篇章/g);
        const endMatches = this.text.match(/毕/g);
        
        if (chapterMatches && endMatches) {
            if (chapterMatches.length !== endMatches.length) {
                this.addDiagnostic(0, 0, `篇章数量(${chapterMatches.length})与结束标记数量(${endMatches.length})不匹配`, DiagnosticSeverity.Error);
            }
        }
    }

    // 检查关键字使用
    private checkKeywords(): void {
        this.lines.forEach((line, lineIndex) => {
            // 检查变量声明
            const varMatch = line.match(/有\s+([一-龥_a-zA-Z0-9]+)\s+者/);
            if (varMatch) {
                const varName = varMatch[1];
                if (!this.isValidIdentifier(varName)) {
                    const charIndex = line.indexOf(varName);
                    this.addDiagnostic(lineIndex, charIndex, `变量名"${varName}"包含非法字符`, DiagnosticSeverity.Error);
                }
            }

            // 检查函数定义
            const funcMatch = line.match(/曰\s+([一-龥_a-zA-Z0-9]+)\s+于/);
            if (funcMatch) {
                const funcName = funcMatch[1];
                if (!this.isValidIdentifier(funcName)) {
                    const charIndex = line.indexOf(funcName);
                    this.addDiagnostic(lineIndex, charIndex, `函数名"${funcName}"包含非法字符`, DiagnosticSeverity.Error);
                }
            }

            // 检查类定义
            const classMatch = line.match(/物之属\s+([一-龥_a-zA-Z0-9]+)/);
            if (classMatch) {
                const className = classMatch[1];
                if (!this.isValidIdentifier(className)) {
                    const charIndex = line.indexOf(className);
                    this.addDiagnostic(lineIndex, charIndex, `类名"${className}"包含非法字符`, DiagnosticSeverity.Error);
                }
            }
        });
    }

    // 检查括号匹配
    private checkBrackets(): void {
        const bracketPairs = [
            { open: '（', close: '）' },
            { open: '「', close: '」' },
            { open: '【', close: '】' },
            { open: '《', close: '》' }
        ];

        this.lines.forEach((line: string, lineIndex: number) => {
            bracketPairs.forEach((pair: { open: string; close: string }) => {
                const openCount = (line.match(new RegExp(pair.open, 'g')) || []).length;
                const closeCount = (line.match(new RegExp(pair.close, 'g')) || []).length;
                
                if (openCount !== closeCount) {
                    this.addDiagnostic(lineIndex, 0, 
                        `括号不匹配：${pair.open}(${openCount}) 与 ${pair.close}(${closeCount})`, 
                        DiagnosticSeverity.Error);
                }
            });
        });
    }

    // 检查函数定义和调用
    private checkFunctions(): void {
        const definedFunctions = new Set<string>();
        const calledFunctions = new Set<string>();

        this.lines.forEach((line: string, lineIndex: number) => {
            // 查找函数定义
            const funcDefMatch = line.match(/曰\s+([一-龥_a-zA-Z0-9]+)\s+于/);
            if (funcDefMatch) {
                definedFunctions.add(funcDefMatch[1]);
            }

            // 查找函数调用
            const funcCallMatches = line.match(/使\s+([一-龥_a-zA-Z0-9]+)\s+于/g);
            if (funcCallMatches) {
                funcCallMatches.forEach((match: string) => {
                    const funcName = match.replace(/使\s+|\s+于/g, '');
                    calledFunctions.add(funcName);
                });
            }
        });

        // 检查未定义的函数调用
        calledFunctions.forEach((funcName: string) => {
            if (!definedFunctions.has(funcName) && !this.isBuiltinFunction(funcName)) {
                this.lines.forEach((line: string, lineIndex: number) => {
                    if (line.includes(`使 ${funcName} 于`)) {
                        const charIndex = line.indexOf(funcName);
                        this.addDiagnostic(lineIndex, charIndex, 
                            `调用了未定义的函数"${funcName}"`, DiagnosticSeverity.Warning);
                    }
                });
            }
        });
    }

    // 检查变量使用
    private checkVariables(): void {
        const definedVariables = new Set<string>();
        const usedVariables = new Set<string>();

        this.lines.forEach((line: string, lineIndex: number) => {
            // 查找变量定义
            const varDefMatch = line.match(/有\s+([一-龥_a-zA-Z0-9]+)\s+者/);
            if (varDefMatch) {
                definedVariables.add(varDefMatch[1]);
            }

            // 查找变量使用（简化版）
            const words = line.split(/\s+/);
            words.forEach((word: string) => {
                if (word.length > 1 && !MOYAN_KEYWORDS.includes(word) && this.isValidIdentifier(word)) {
                    usedVariables.add(word);
                }
            });
        });

        // 检查未定义的变量使用
        usedVariables.forEach((varName: string) => {
            if (!definedVariables.has(varName) && !this.isBuiltinVariable(varName)) {
                this.lines.forEach((line: string, lineIndex: number) => {
                    if (line.includes(varName)) {
                        const charIndex = line.indexOf(varName);
                        this.addDiagnostic(lineIndex, charIndex, 
                            `使用了未定义的变量"${varName}"`, DiagnosticSeverity.Warning);
                    }
                });
            }
        });
    }

    // 添加诊断信息
    private addDiagnostic(line: number, character: number, message: string, severity: DiagnosticSeverity): void {
        const range = Range.create(
            Position.create(line, character),
            Position.create(line, character + 1)
        );

        const diagnostic: Diagnostic = {
            severity,
            range,
            message,
            source: '墨言'
        };

        this.diagnostics.push(diagnostic);
    }

    // 检查标识符是否有效
    private isValidIdentifier(name: string): boolean {
        return /^[一-龥_a-zA-Z][一-龥_a-zA-Z0-9]*$/.test(name);
    }

    // 检查是否为内置函数
    private isBuiltinFunction(name: string): boolean {
        const builtinFunctions = ['书'];
        return builtinFunctions.includes(name);
    }

    // 检查是否为内置变量
    private isBuiltinVariable(name: string): boolean {
        const builtinVariables = ['真', '伪', '无'];
        return builtinVariables.includes(name);
    }
}

// 初始化
connection.onInitialize((params: InitializeParams) => {
    const capabilities = params.capabilities;

    hasConfigurationCapability = !!(
        capabilities.workspace && !!capabilities.workspace.configuration
    );
    hasWorkspaceFolderCapability = !!(
        capabilities.workspace && !!capabilities.workspace.workspaceFolders
    );
    hasDiagnosticRelatedInformationCapability = !!(
        capabilities.textDocument &&
        capabilities.textDocument.publishDiagnostics &&
        capabilities.textDocument.publishDiagnostics.relatedInformation
    );

    const result: InitializeResult = {
        capabilities: {
            textDocumentSync: TextDocumentSyncKind.Incremental,
            completionProvider: {
                resolveProvider: true,
                triggerCharacters: ['.', '、', ' ']
            },
            documentFormattingProvider: true,
            executeCommandProvider: {
                commands: ['moyan.runDiagnostics']
            }
        }
    };

    if (hasWorkspaceFolderCapability) {
        result.capabilities.workspace = {
            workspaceFolders: {
                supported: true
            }
        };
    }

    return result;
});

connection.onInitialized(() => {
    if (hasConfigurationCapability) {
        connection.client.register(DidChangeConfigurationNotification.type, undefined);
    }
    if (hasWorkspaceFolderCapability) {
        connection.workspace.onDidChangeWorkspaceFolders((_event: { added: WorkspaceFolder[]; removed: WorkspaceFolder[] }) => {
            connection.console.log('Workspace folder change event received.');
        });
    }
});

// 配置
interface MoyanSettings {
    maxNumberOfProblems: number;
    enableDiagnostics: boolean;
    enableFormatting: boolean;
    enableAutoCompletion: boolean;
}

const defaultSettings: MoyanSettings = {
    maxNumberOfProblems: 100,
    enableDiagnostics: true,
    enableFormatting: true,
    enableAutoCompletion: true
};

let globalSettings: MoyanSettings = defaultSettings;
const documentSettings: Map<string, Thenable<MoyanSettings>> = new Map();

connection.onDidChangeConfiguration((change: { settings: any }) => {
    if (hasConfigurationCapability) {
        documentSettings.clear();
    } else {
        globalSettings = <MoyanSettings>(
            (change.settings.moyan || defaultSettings)
        );
    }

    documents.all().forEach(validateTextDocument);
});

function getDocumentSettings(resource: string): Thenable<MoyanSettings> {
    if (!hasConfigurationCapability) {
        return Promise.resolve(globalSettings);
    }
    let result = documentSettings.get(resource);
    if (!result) {
        result = connection.workspace.getConfiguration({
            scopeUri: resource,
            section: 'moyan'
        }) as Thenable<MoyanSettings>;
        if (result) {
            documentSettings.set(resource, result);
        } else {
            result = Promise.resolve(globalSettings);
        }
    }
    return result;
}

// 验证文档
async function validateTextDocument(textDocument: TextDocument): Promise<void> {
    const settings = await getDocumentSettings(textDocument.uri);
    
    if (!settings.enableDiagnostics) {
        return;
    }

    const text = textDocument.getText();
    const checker = new MoyanSyntaxChecker(text);
    const diagnostics = checker.check();

    // 限制诊断数量
    const limitedDiagnostics = diagnostics.slice(0, settings.maxNumberOfProblems);

    connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: limitedDiagnostics });
}

// 文档变化时验证
documents.onDidChangeContent((change: { document: TextDocument }) => {
    validateTextDocument(change.document);
});

// 文档打开时验证
documents.onDidOpen((change: { document: TextDocument }) => {
    validateTextDocument(change.document);
});

// 自动补全
connection.onCompletion(
    (_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => {
        return MOYAN_KEYWORDS.map(keyword => ({
            label: keyword,
            kind: CompletionItemKind.Keyword,
            data: keyword
        }));
    }
);

connection.onCompletionResolve(
    (item: CompletionItem): CompletionItem => {
        item.detail = '墨言关键字';
        item.documentation = `墨言编程语言关键字: ${item.data}`;
        return item;
    }
);

// 格式化
connection.onDocumentFormatting((params: DocumentFormattingParams): TextEdit[] => {
    const document = documents.get(params.textDocument.uri);
    if (!document) {
        return [];
    }
    
    const lines = document.getText().split('\n');
    const edits: TextEdit[] = [];
    
    lines.forEach((line: string, lineIndex: number) => {
        const trimmed = line.trim();
        if (trimmed.length === 0) {
            return;
        }
        
        // 简单的格式化规则
        let formatted = trimmed;
        
        // 在关键字前后添加空格
        MOYAN_KEYWORDS.forEach(keyword => {
            const regex = new RegExp(`(${keyword})([^\\s])`, 'g');
            formatted = formatted.replace(regex, '$1 $2');
        });
        
        if (formatted !== line) {
            edits.push({
                range: {
                    start: { line: lineIndex, character: 0 },
                    end: { line: lineIndex, character: line.length }
                },
                newText: formatted
            });
        }
    });
    
    return edits;
});

// 执行命令
connection.onExecuteCommand(async (params: { command: string; arguments?: any[] }) => {
    if (params.command === 'moyan.runDiagnostics') {
        const uri = params.arguments?.[0];
        if (uri) {
            const document = documents.get(uri);
            if (document) {
                await validateTextDocument(document);
            }
        }
    }
});

// 监听文档
documents.listen(connection);

// 启动连接
connection.listen();